package com.ruoyi.js.controller;

import java.io.IOException;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import com.ruoyi.common.config.Global;
import com.ruoyi.common.json.JSONObject;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.file.FileUploadUtils;
import com.ruoyi.js.domain.*;
import com.ruoyi.js.service.IJsItemService;
import com.ruoyi.js.service.IJsPlaceService;
import com.ruoyi.js.service.IJsPlayerService;
import com.ruoyi.js.utils.RandomUtils;
import com.ruoyi.js.webscoket.WebSocketUsers;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.*;
import com.ruoyi.common.annotation.Log;
import com.ruoyi.common.enums.BusinessType;
import com.ruoyi.js.service.IJsRegisterService;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.utils.poi.ExcelUtil;
import com.ruoyi.common.core.page.TableDataInfo;
import org.springframework.web.multipart.MultipartFile;

/**
 * 报名 Controller
 * 
 * @author greejoy
 * @date 2024-04-22
 */
@Controller
@RequestMapping("/js/register")
public class JsRegisterController extends BaseController
{
    private String prefix = "js/register";

    @Autowired
    private IJsRegisterService jsRegisterService;

    @Autowired
    private IJsItemService jsItemService;

    @Autowired
    private IJsPlayerService jsPlayerService;

    @Autowired
    private IJsPlaceService jsPlaceService;

    @RequiresPermissions("js:register:view")
    @GetMapping()
    public String register(@CookieValue("app_match_id") Long matchId, ModelMap mmap)
    {
        List<JsItem> itemList = jsItemService.selectJsItemList(new JsItem(matchId));
        mmap.put("itemList", itemList);
        return prefix + "/register";
    }

    /**
     * 查询报名 列表
     */
    @RequiresPermissions("js:register:list")
    @PostMapping("/list")
    @ResponseBody
    public TableDataInfo list(@CookieValue("app_match_id") Long matchId, JsRegister jsRegister)
    {
        jsRegister.setMatchId(matchId);
        startPage();
        List<JsRegister> list = jsRegisterService.selectJsRegisterList(jsRegister);
        return getDataTable(list);
    }

    /**
     * 导出报名 列表
     */
    @RequiresPermissions("js:register:export")
    @Log(title = "报名 ", businessType = BusinessType.EXPORT)
    @PostMapping("/export")
    @ResponseBody
    public AjaxResult export(@CookieValue("app_match_id") Long matchId, JsRegister jsRegister)
    {
        jsRegister.setMatchId(matchId);
        List<JsRegister> registerList = jsRegisterService.selectJsRegisterList(jsRegister);
        List<JsRegisterTmpl> tmplList = new ArrayList<>();
        for (JsRegister register : registerList) {
            JsRegisterTmpl tmpl = new JsRegisterTmpl();
            tmpl.setItemName(register.getItemName());
            tmpl.setPlayerName(register.getPlayerName());
            tmpl.setPlayerIdcard(register.getPlayerIdcard());
            tmpl.setWorksName(register.getWorksName());
            tmpl.setPlaceName(register.getPlaceName());
            tmpl.setSession(register.getSession());
            tmpl.setOdr(register.getOdr());
            tmplList.add(tmpl);
        }
        ExcelUtil<JsRegisterTmpl> util = new ExcelUtil<JsRegisterTmpl>(JsRegisterTmpl.class);
        return util.exportExcel(tmplList, "register");
    }

    /**
     * 新增报名 
     */
    @GetMapping("/add")
    public String add(@CookieValue("app_match_id") Long matchId, ModelMap mmap)
    {
        List<JsItem> itemList = jsItemService.selectJsItemList(new JsItem(matchId));
        mmap.put("itemList", itemList);
        List<JsPlayer> playerList = jsPlayerService.selectJsPlayerList(null);
        mmap.put("playerList", playerList);
        return prefix + "/add";
    }

    /**
     * 新增保存报名 
     */
    @RequiresPermissions("js:register:add")
    @Log(title = "报名 ", businessType = BusinessType.INSERT)
    @PostMapping("/add")
    @ResponseBody
    public AjaxResult addSave(JsRegister jsRegister)
    {
        return toAjax(jsRegisterService.insertJsRegister(jsRegister));
    }

    /**
     * 修改报名 
     */
    @GetMapping("/edit/{id}")
    public String edit(@CookieValue("app_match_id") Long matchId, @PathVariable("id") Long id, ModelMap mmap)
    {
        List<JsItem> itemList = jsItemService.selectJsItemList(new JsItem(matchId));
        mmap.put("itemList", itemList);
        List<JsPlayer> playerList = jsPlayerService.selectJsPlayerList(null);
        mmap.put("playerList", playerList);

        JsRegister jsRegister = jsRegisterService.selectJsRegisterById(id);
        mmap.put("jsRegister", jsRegister);
        return prefix + "/edit";
    }

    /**
     * 修改保存报名 
     */
    @RequiresPermissions("js:register:edit")
    @Log(title = "报名 ", businessType = BusinessType.UPDATE)
    @PostMapping("/edit")
    @ResponseBody
    public AjaxResult editSave(JsRegister jsRegister, MultipartFile photoFile, MultipartFile musicFile)
    {

        // 上传文件路径
        String filePath = Global.getUploadPath();

        if(photoFile != null){
            String photo = null;
            try {
                photo = FileUploadUtils.upload(filePath, photoFile);
            } catch (IOException e) {
                e.printStackTrace();
            }
            jsRegister.setPhoto(photo);
        }

        if(musicFile != null){
            String music = null;
            try {
                music = FileUploadUtils.upload(filePath, musicFile);
            } catch (Exception e) {
                e.printStackTrace();
            }
            jsRegister.setMusic(music);
        }
        
        return toAjax(jsRegisterService.updateJsRegister(jsRegister));
    }

    /**
     * 删除报名 
     */
    @RequiresPermissions("js:register:remove")
    @Log(title = "报名 ", businessType = BusinessType.DELETE)
    @PostMapping( "/remove")
    @ResponseBody
    public AjaxResult remove(String ids)
    {
        return toAjax(jsRegisterService.deleteJsRegisterByIds(ids));
    }


    @RequiresPermissions("js:register:view")
    @GetMapping("/arrange")
    public String arrange(@CookieValue("app_match_id") Long matchId, ModelMap mmap)
    {
        List<JsPlace> placeList = jsPlaceService.selectJsPlaceList(new JsPlace(matchId));
        mmap.put("placeList", placeList);

        return prefix + "/arrange";
    }

    /**
     * 查询抽签
     */
    @RequiresPermissions("js:register:list")
    @PostMapping("/listArrange")
    @ResponseBody
    public TableDataInfo listArrange(JsRegister jsRegister)
    {
        startPage();

        List<JsRegister> registerList = jsRegisterService.selectJsRegisterListToMatch(jsRegister);

        return getDataTable(registerList);
    }

    /**
     * 修改编排
     */
    @GetMapping("/editArrange/{id}")
    public String editArrange(@CookieValue("app_match_id") Long matchId, @PathVariable("id") Long id, ModelMap mmap)
    {

        JsRegister jsRegister = jsRegisterService.selectJsRegisterById(id);
        mmap.put("jsRegister", jsRegister);

        List<JsPlace> placeList = jsPlaceService.selectJsPlaceList(new JsPlace(matchId));
        mmap.put("placeList", placeList);

        return prefix + "/editArrange";
    }

    @PostMapping("/editArrange")
    @ResponseBody
    public AjaxResult editArrange(Long registerId, Long placeId, Integer session, Integer odr)
    {
        JsRegister register = jsRegisterService.selectJsRegisterById(registerId);
        register.setPlaceId(placeId);
        register.setSession(session);
        register.setOdr(odr);
        jsRegisterService.updateJsRegister(register);
        return AjaxResult.success();
    }

    /**
     * 刷新打分推送列表
     */
    @GetMapping("/sendToRefreshRegisterList")
    @ResponseBody
    public AjaxResult sendToRefreshRegisterList()
    {

        JSONObject object = new JSONObject();
        object.set("type", "refreshRegisterList");

        // 发送打分信息
        WebSocketUsers.sendMessageToUsersByText(object.toCompactString());

        return AjaxResult.success();
    }

    @RequiresPermissions("js:register:view")
    @GetMapping("/importTemplate")
    @ResponseBody
    public AjaxResult importTemplate()
    {
        ExcelUtil<JsRegisterTmpl> util = new ExcelUtil(JsRegisterTmpl.class);
        return util.importTemplateExcel("报名导入模版");
    }

    @RequiresPermissions("js:register:add")
    @PostMapping("/importData")
    @ResponseBody
    public AjaxResult importData(@CookieValue("app_match_id") Long matchId, MultipartFile file) throws Exception
    {
        ExcelUtil<JsRegisterTmpl> util = new ExcelUtil(JsRegisterTmpl.class);
        List<JsRegisterTmpl> registerTmplList = util.importExcel(file.getInputStream());

        // 去除空行
        registerTmplList = registerTmplList.stream().filter(f -> f.getItemName() != null && f.getItemName().trim().length() > 0).collect(Collectors.toList());

        if (StringUtils.isNull(registerTmplList) || registerTmplList.size() == 0)
        {
            return AjaxResult.error("导入数据不能为空！");
        }


        List<JsItem> itemList = jsItemService.selectJsItemList(new JsItem(matchId));
        List<JsPlace> placeList = jsPlaceService.selectJsPlaceList(new JsPlace(matchId));

        Map<String, JsItem> itemMap = itemList.stream().collect(Collectors.toMap(JsItem::getName, v -> v));
        Map<String, JsPlace> placeMap = placeList.stream().collect(Collectors.toMap(JsPlace::getName, v -> v));

        int successInsertNum = 0;
        int successUpdateNum = 0;
        int failNum = 0;
        StringBuilder resultMsg = new StringBuilder();
        StringBuilder failMsg = new StringBuilder();
        for (JsRegisterTmpl registerTmpl : registerTmplList) {

            String itemName = registerTmpl.getItemName();
            String playerNameStr = registerTmpl.getPlayerName();
            String playerIdcardStr = registerTmpl.getPlayerIdcard();
            String placeName = registerTmpl.getPlaceName();

            JsItem item = itemMap.get(itemName);
            if(item == null){
                failNum++;
                String msg =  "项目不存在";
                failMsg.append("<br/>" + failNum + "、" + msg + "-" + itemName + "-" + playerNameStr);
                continue;
            }

            // 场地不存在
            JsPlace place = placeMap.get(placeName);
            if(StringUtils.isNotEmpty(placeName)){
                if(place == null){
                    failNum++;
                    String msg =  "场地不存在";
                    failMsg.append("<br/>" + failNum + "、" + msg + "-" + placeName + "-" + playerNameStr);
                    continue;
                }
            }

            // 姓名不能为空
            if( StringUtils.isEmpty(playerNameStr)){
                failNum++;
                String msg =  "姓名不能为空";
                failMsg.append("<br/>" + failNum + "、" + msg + "-" + itemName + "-" + playerNameStr);
                continue;
            }

            // 选手信息，格式为 郭扬,罗凯瑞
            // 身份证信息 格式为 510303201009121316,510311201202226638
            playerNameStr = playerNameStr.replaceAll("，", ",").replaceAll("、", ",").replaceAll("'", "").replaceAll("‘", "").trim();
            playerIdcardStr = playerIdcardStr.replaceAll("，", ",").replaceAll("、", ",").replaceAll("'", "").replaceAll("‘", "").trim();
            String[] nameStrArr = playerNameStr.split(",");
            String[] idcardStrArr = StringUtils.isNotEmpty(playerIdcardStr) ? playerIdcardStr.split(",") : new String[0];

            // 身份证不存在，随机生成R开头的随机身份证
            if(idcardStrArr.length == 0){
                idcardStrArr = new String[nameStrArr.length];
                for (int i = 0; i < nameStrArr.length; i++) {
                    String rIdcard = RandomUtils.buildRIdcard();
                    idcardStrArr[i] = rIdcard;
                }
            }

            // 姓名和身份证个数不匹配
            if(nameStrArr.length != idcardStrArr.length){
                failNum++;
                String msg =  "姓名和身份证个数不匹配";
                failMsg.append("<br/>" + failNum + "、" + msg + "-" + itemName + "-" + playerNameStr);
                continue;
            }

            List<JsPlayer> playerList = new ArrayList<>();

            for (int i = 0; i < nameStrArr.length; i++) {
                String name = nameStrArr[i];
                String idcard = idcardStrArr[i];
                JsPlayer player = new JsPlayer();
                player.setIdcard(idcard);
                List<JsPlayer> dbPlayerList = jsPlayerService.selectJsPlayerList(player);
                if (dbPlayerList.size() > 0){
                    player = dbPlayerList.get(0);
                }else {
                    player.setName(name);
                    jsPlayerService.insertJsPlayer(player);
                }
                playerList.add(player);

            }

            String playerIds = playerList.stream().sorted(Comparator.comparing(JsPlayer::getId)).map(m -> m.getId().toString()).collect(Collectors.joining(","));

            JsRegister newRegister = new JsRegister(item.getId());
            newRegister.setPlayerIds(playerIds);

            List<JsRegister> dbRegisterList = jsRegisterService.selectJsRegisterList(newRegister);

            String worksName = registerTmpl.getWorksName();
            Integer session = registerTmpl.getSession();
            Integer odr = registerTmpl.getOdr();

            if(dbRegisterList.size() == 0){
                newRegister.setWorksName(worksName);
                if(place != null){
                    newRegister.setPlaceId(place.getId());
                }
                newRegister.setSession(session);
                newRegister.setOdr(odr);
                jsRegisterService.insertJsRegister(newRegister);
                successInsertNum++;
            }else {
                JsRegister dbRegister = dbRegisterList.get(0);
                if(StringUtils.isNotEmpty(worksName)){
                    dbRegister.setWorksName(worksName);
                }
                if(place != null){
                    dbRegister.setPlaceId(place.getId());
                }
                if(session != null){
                    dbRegister.setSession(session);
                }
                if(odr != null){
                    dbRegister.setOdr(odr);
                }
                jsRegisterService.updateJsRegister(dbRegister);
                successUpdateNum++;
            }


        }

        resultMsg.insert(0, "数据导入完成，成功 " + (successInsertNum + successUpdateNum) + " 条，新增 " + successInsertNum + " 条，更新 " + successUpdateNum + " 条，失败 " + failNum + " 条");
        if (failNum > 0) {
            failMsg.insert(0, "<br/>失败数据如下：");
            resultMsg.append(failMsg);
        }

        return AjaxResult.success(resultMsg.toString());
    }

}
